package com.cz.run.web;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.cz.run.beans.base.ReturnDTO;
import com.cz.run.beans.mysql.*;
import com.cz.run.beans.po.BindPO;
import com.cz.run.beans.po.WechatLoginPo;
import com.cz.run.beans.po.user.LoginGetPO;
import com.cz.run.beans.po.user.ModifyPassPO;
import com.cz.run.beans.po.user.RegisterPO;
import com.cz.run.beans.po.user.SendCodePO;
import com.cz.run.constants.ConstantKey;
import com.cz.run.enums.SystemCodeEnum;
import com.cz.run.service.*;
import com.cz.run.utils.*;
import com.cz.run.wechat.model.WechatLoginModel;
import com.cz.run.wechat.model.WechatTokenResponse;
import com.cz.run.wechat.model.WechatUerInfoResponse;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @Description: TODO()
 * @auther:CAIYJ
 * @Date:2018/5/21 14:46
 */
@RestController
@RequestMapping(value = "/login")
public class LoginServer {

    @Autowired
    private IUserBaseService userBaseService;

    @Autowired
    private IUserPointService userPointService;

    @Autowired
    private IUserReferralService iUserReferralService;

    @Autowired
    private IUserForceCoefficientService userForceCoefficientService;

    @Autowired
    private IUserForceService userForceService;


    @Autowired
    private ISmsCodeService iSmsCodeService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IUserExtWechatProfileService iUserExtWechatProfileService;

    private static final String WECHAT_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={secret}&code={code}&grant_type=authorization_code";// 微信获取token地址

    private static final String WECHAT_USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}";// 微信获取用户信息地址

    private static final String WECHAT_LANG = "zh_CN";// 微信国家地区语言版本

    private static final String CHARSET_NAME = "UTF-8";// 微信获取用户信息地址

    private static final String appId = "wx9a8273500c59a990";
    private static final String secret = "69b44cf8b0b487f259787a74fa245e6d";
    /**
     * 登陆页
     *
     * @return
     */
    @ApiOperation(value = "登陆", notes = "登陆", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/login")
    public ReturnDTO<WechatLoginModel> loginGet(@RequestBody LoginGetPO po) {
        if (StringUtils.isEmpty(po.getPassword()) || StringUtils.isEmpty(po.getPassword())) {
            return ReturnDTO.fail(SystemCodeEnum.userpwd_not_exist);
        }


        EntityWrapper<UserBase> ew = new EntityWrapper<>();
        ew.where(StringUtils.isNotEmpty(po.getUsername()), "user_name = {0} ", po.getUsername());
        UserBase userBase = userBaseService.selectOne(ew);
        if(null!=userBase&&0==userBase.getStatus()){
            return ReturnDTO.fail("账户被封禁，请联系客服");
        }
        if (null == userBase) {
            ew = new EntityWrapper<>();
            ew.where(StringUtils.isNotEmpty(po.getUsername()), "phone = {0} ", po.getUsername());
            userBase = userBaseService.selectOne(ew);
            if(null!=userBase&&0==userBase.getStatus()){
                return ReturnDTO.fail("账户被封禁，请联系客服");
            }
            if (null == userBase) {
                return ReturnDTO.fail(SystemCodeEnum.userpwd_not_exist);
            }
        }
        if (StringUtils.isNotEmpty(userBase.getPassword()) && !userBase.getPassword().equals(MD5.GetMD5Code(po.getPassword()))) {
            return ReturnDTO.fail(SystemCodeEnum.userpwd_not_exist);
        }
        String token = Jwts.builder().setSubject(userBase.getId().toString())
                .setExpiration(new Date(new Date().getTime()+365*24*60*60*1000))
                .signWith(SignatureAlgorithm.HS512, ConstantKey.SIGNING_KEY)
                .compact();
        WechatLoginModel wechatLoginModel = new WechatLoginModel();
        EntityWrapper<UserExtWechatProfile> entityWrapper = new EntityWrapper<>();
        entityWrapper.where("user_id={0}",userBase.getId());
        if(null==iUserExtWechatProfileService.selectOne(entityWrapper)){
            wechatLoginModel.setFlag(false);
            wechatLoginModel.setUserId(userBase.getId());

            return ReturnDTO.success(wechatLoginModel);
        }
        wechatLoginModel.setToken(token);
        return ReturnDTO.success(wechatLoginModel);
    }

    @ApiOperation(value = "微信登陆", notes = "微信登陆", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/weLogin")
    public ReturnDTO<WechatLoginModel> weLogin(@RequestBody WechatLoginPo po, HttpServletRequest request) {
        WechatLoginModel wechatLoginModel = new WechatLoginModel();
        if (StringUtils.isEmpty(po.getCode())) {
            return ReturnDTO.fail(SystemCodeEnum.userpwd_not_exist);
        }
        restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());

        Map<String, String> params = new HashMap<>();
        params.put("appId", appId);
        params.put("secret", secret);
        params.put("code", po.getCode());
        WechatTokenResponse wechatTokenResponse = restTemplate.getForObject(WECHAT_TOKEN_URL,  WechatTokenResponse.class,params);

        if (null == wechatTokenResponse) {
            return ReturnDTO.fail(SystemCodeEnum.http_status_internal_server_error);
        }

        if (null == wechatTokenResponse || null != wechatTokenResponse.getErrcode()) {
            return ReturnDTO.fail(SystemCodeEnum.http_status_internal_server_error);
        }

        Map<String, String> params1 = new HashMap<>();
        params1.put("access_token", wechatTokenResponse.getAccess_token());
        params1.put("openid", wechatTokenResponse.getOpenid());
        WechatUerInfoResponse wechatUerInfoResponse = restTemplate.getForObject(WECHAT_USER_INFO_URL,  WechatUerInfoResponse.class,params1);

        if (null == wechatUerInfoResponse) {
            return ReturnDTO.fail(SystemCodeEnum.http_status_internal_server_error);
        }

        if (null == wechatUerInfoResponse || null != wechatUerInfoResponse.getErrcode()) {
            return ReturnDTO.fail(SystemCodeEnum.http_status_internal_server_error);
        }

        EntityWrapper<UserExtWechatProfile> ew = new EntityWrapper<>();
        ew.where("unionid = {0}",wechatUerInfoResponse.getUnionid());
        UserExtWechatProfile userExtWechatProfile1 =iUserExtWechatProfileService.selectOne(ew);

        Integer userId =0;

        if(null!=userExtWechatProfile1)
         userId =userExtWechatProfile1.getUserId();

        if(!StringUtils.isEmpty(po.getUserId()))
         userId = Integer.parseInt(po.getUserId());

        if(null==userExtWechatProfile1){

            UserBase userBase = new UserBase();
            if(StringUtils.isEmpty(po.getUserId())||null==userBaseService.selectById(Long.parseLong(po.getUserId()))){
                userBase.setRegistIp(RequestUtil.getIpAddr(request));
                userBase.setRegistTime(new Date());
                userBase.setNickName(wechatUerInfoResponse.getNickname());
                 userBaseService.insert(userBase);
                userId = userBase.getId();
                wechatLoginModel.setFlag(false);
            }

            UserExtWechatProfile userExtWechatProfile = new UserExtWechatProfile();

            final BeanCopier bc  = BeanCopier.create(WechatUerInfoResponse.class,UserExtWechatProfile.class,false);
            bc.copy(wechatUerInfoResponse,userExtWechatProfile,null);
            userExtWechatProfile.setHeadImgUrl(wechatUerInfoResponse.getHeadimgurl());
            userExtWechatProfile.setOpenidBiz(wechatUerInfoResponse.getOpenid());
            userExtWechatProfile.setUserId(userId);
            userExtWechatProfile.setNickName(wechatUerInfoResponse.getNickname());

            iUserExtWechatProfileService.insert(userExtWechatProfile);

        }else{

            final BeanCopier bc  = BeanCopier.create(WechatUerInfoResponse.class,UserExtWechatProfile.class,false);
            bc.copy(wechatUerInfoResponse,userExtWechatProfile1,null);
            userExtWechatProfile1.setHeadImgUrl(wechatUerInfoResponse.getHeadimgurl());
            userExtWechatProfile1.setOpenidBiz(wechatUerInfoResponse.getOpenid());
            userExtWechatProfile1.setUserId(userId);
            iUserExtWechatProfileService.updateById(userExtWechatProfile1);
            userExtWechatProfile1.setNickName(wechatUerInfoResponse.getNickname());




            UserBase userBase = new UserBase();
            userBase.setNickName(wechatUerInfoResponse.getNickname());
            userBase.setId(userId);
            userBaseService.updateById(userBase);

            UserBase userBase1 =userBaseService.selectById(userId);
            if(null!=userBase1&&0==userBase1.getStatus()){
                return ReturnDTO.fail("账户被封禁，请联系客服");
            }
            if(StringUtils.isEmpty(userBase1.getPhone())){
                wechatLoginModel.setFlag(false);
            }
        }

        String token = Jwts.builder().setSubject(userId.toString())
                .setExpiration(new Date(new Date().getTime()+365*24*60*60*1000))
                .signWith(SignatureAlgorithm.HS512, ConstantKey.SIGNING_KEY)
                .compact();
        wechatLoginModel.setToken(token);
        wechatLoginModel.setUserId(userId);
        return ReturnDTO.success(wechatLoginModel);
    }

    @ApiOperation(value = "绑定手机号", notes = "绑定手机号", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/binding")
    public ReturnDTO<String> binding(@RequestBody BindPO po, HttpServletRequest request) throws Exception {
        if (StringUtils.isEmpty(po.getPassword()) || StringUtils.isEmpty(po.getPhone())||StringUtils.isEmpty(po.getUserId())) {
            return ReturnDTO.fail("存在空值，请重新输入");
        }
        if (!RegularUtil.isChinaPhoneLegal(po.getPhone())) {
            return ReturnDTO.fail("手机号不正确！请重新输入");
        }

        EntityWrapper<SmsCode> ew = new EntityWrapper<>();
        ew.where("phone = {0} ",po.getPhone()).orderBy("create_time desc limit 1");
        SmsCode smsCode =iSmsCodeService.selectOne(ew);

        if (null==smsCode||!StringUtils.equals(po.getCode(),smsCode.getCode())||smsCode.getDeadTime().getTime()<new Date().getTime()) {
            return ReturnDTO.fail("验证码不正确或已过期！请重新输入");
        }

        UserBase userBase = new UserBase();
        userBase.setPassword(MD5.GetMD5Code(po.getPassword()));
        userBase.setPhone(po.getPhone());
        userBase.setRegistIp(RequestUtil.getIpAddr(request));
        userBase.setNickName(ConstantKey.BASE_NICKNAME + ShareCodeUtil.toSerialCode(Long.parseLong(po.getPhone())));
        userBase.setId(Integer.parseInt(po.getUserId()));
        try {
            boolean result = userBaseService.updateById(userBase);
            if (result) {
                UserPoint userPoint = new UserPoint();
                userPoint.setUserId(userBase.getId());
                userPoint.setPoint(ConstantKey.DEFAULT_POINT);
            }
        } catch (DuplicateKeyException e) {
            return ReturnDTO.fail(SystemCodeEnum.user_exist);
        }
        UserReferral userReferral = new UserReferral();
        userReferral.setUserId(userBase.getId());
        userReferral.setCode(ShareCodeUtil.toSerialCode(userBase.getId()));
        iUserReferralService.insert(userReferral);
        UserForceCoefficient userForceCoefficient = new UserForceCoefficient();
        userForceCoefficient.setUserId(userBase.getId());
        userForceCoefficientService.insert(userForceCoefficient);
        UserForce userForce = new UserForce();
        userForce.setUserId(userBase.getId());
        userForce.setLevel("雏鸡");
        userForceService.insert(userForce);
        UserPoint userPoint = new UserPoint();
        userPoint.setUserId(userBase.getId());
        userPointService.insert(userPoint);
        return ReturnDTO.success(String.valueOf(userBase.getId()));
    }

    @ApiOperation(value = "注册", notes = "注册", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/register")
    public ReturnDTO<String> register(@RequestBody RegisterPO po, HttpServletRequest request) throws Exception {
        if (StringUtils.isEmpty(po.getPassword()) || StringUtils.isEmpty(po.getPhone())) {
            return ReturnDTO.fail("存在空值，请重新输入");
        }
        if (!RegularUtil.isChinaPhoneLegal(po.getPhone())) {
            return ReturnDTO.fail("手机号不正确！请重新输入");
        }

        EntityWrapper<SmsCode> ew = new EntityWrapper<>();
        ew.where("phone = {0} ",po.getPhone()).orderBy("create_time desc limit 1");
        SmsCode smsCode =iSmsCodeService.selectOne(ew);

        if (null==smsCode||!StringUtils.equals(po.getCode(),smsCode.getCode())||smsCode.getDeadTime().getTime()<new Date().getTime()) {
            return ReturnDTO.fail("验证码不正确或已过期！请重新输入");
        }

        UserBase userBase = new UserBase();
        userBase.setPassword(MD5.GetMD5Code(po.getPassword()));
        userBase.setPhone(po.getPhone());
        userBase.setRegistIp(RequestUtil.getIpAddr(request));
        userBase.setRegistTime(new Date());
        userBase.setNickName(ConstantKey.BASE_NICKNAME + ShareCodeUtil.toSerialCode(Long.parseLong(po.getPhone())));
        try {
            boolean result = userBaseService.insert(userBase);
            if (result) {
                UserPoint userPoint = new UserPoint();
                userPoint.setUserId(userBase.getId());
                userPoint.setPoint(ConstantKey.DEFAULT_POINT);
            }
        } catch (DuplicateKeyException e) {
            return ReturnDTO.fail(SystemCodeEnum.user_exist);
        }
        UserReferral userReferral = new UserReferral();
        userReferral.setUserId(userBase.getId());
        userReferral.setCode(ShareCodeUtil.toSerialCode(userBase.getId()));
        iUserReferralService.insert(userReferral);
        UserForceCoefficient userForceCoefficient = new UserForceCoefficient();
        userForceCoefficient.setUserId(userBase.getId());
        userForceCoefficientService.insert(userForceCoefficient);
        UserForce userForce = new UserForce();
        userForce.setUserId(userBase.getId());
        userForce.setLevel("雏鸡");
        userForceService.insert(userForce);
        UserPoint userPoint = new UserPoint();
        userPoint.setUserId(userBase.getId());
        userPointService.insert(userPoint);

        return ReturnDTO.success(String.valueOf(userBase.getId()));
    }

    @ApiOperation(value = "忘记密码", notes = "忘记密码", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/modifyPass")
    public ReturnDTO<String> modifyPass(@RequestBody ModifyPassPO po, HttpServletRequest request) {
        if (StringUtils.isEmpty(po.getPassword())||StringUtils.isEmpty(po.getPhone())) {
            return ReturnDTO.fail(SystemCodeEnum.error_invalid_argument);
        }

        EntityWrapper<UserBase> ew = new EntityWrapper<>();
        ew.where("phone = {0}",po.getPhone());
        UserBase userBase = userBaseService.selectOne(ew);
        if(null!=userBase&&0==userBase.getStatus()){
            return ReturnDTO.fail("账户被封禁，请联系客服");
        }
        userBase.setPassword(MD5.GetMD5Code(po.getPassword()));
        userBaseService.updateById(userBase);
        return ReturnDTO.success("修改成功");
    }

    @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = "/sendCode")
    public ReturnDTO<String> sendCode(@RequestBody SendCodePO po) throws Exception {

        if (!RegularUtil.isChinaPhoneLegal(po.getPhone())) {
            return ReturnDTO.fail("手机号不正确！请重新输入");
        }

        String code = SmsUtil.getCode(6);
        SmsUtil.sendMsg(code,po.getPhone());

        SmsCode smsCode = new SmsCode();
        smsCode.setCode(code);
        smsCode.setPhone(po.getPhone());
        smsCode.setDeadTime(new Date(new Date().getTime()+300000));
        smsCode.setCreateTime(new Date());
        iSmsCodeService.insert(smsCode);
        return ReturnDTO.success("成功");
    }

    public static void main(String[] args){
        System.out.print(DateUtil.currentTimeMillisCN3(new Date(new Date().getTime()+365*24*60*60*1000)));
    }

    public class WxMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
        public WxMappingJackson2HttpMessageConverter(){
            List<MediaType> mediaTypes = new ArrayList<>();
            mediaTypes.add(MediaType.TEXT_PLAIN);
            setSupportedMediaTypes(mediaTypes);
        }
    }
}
